package com.nbufe.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nbufe.domain.ResponseResult;
import com.nbufe.domain.dto.ModifyElectricHeatInfoDto;
import com.nbufe.domain.dto.ModifyFossiFuelInfoDto;
import com.nbufe.domain.dto.QueryElectricHeatDTO;
import com.nbufe.domain.entity.ElectricHeat;
import com.nbufe.domain.entity.EmissionOrigin;
import com.nbufe.domain.entity.Process;
import com.nbufe.domain.form.QueryElectricHeatForm;
import com.nbufe.domain.vo.ElectricHeatBuyInfoVo;
import com.nbufe.domain.vo.PageVo;
import com.nbufe.domain.vo.electricheat.CalcElectricHeatCarbonVo;
import com.nbufe.enums.AppHttpCodeEnum;
import com.nbufe.exception.SystemException;
import com.nbufe.mapper.ElectricHeatMapper;
import com.nbufe.mapper.ProcessMapper;
import com.nbufe.service.CarbonStatisticsService;
import com.nbufe.service.DataService;
import com.nbufe.service.ElectricHeatService;
import com.nbufe.utils.BeanCopyUtils;
import com.nbufe.utils.HttpContextUtils;
import com.nbufe.utils.UnderUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 电力、热力CO2排放表(ElectricHeat)表服务实现类
 *
 * @author LZH
 * @since 2023-04-01 10:10:19
 */
@Service("electricHeatService")
public class ElectricHeatServiceImpl extends ServiceImpl<ElectricHeatMapper, ElectricHeat> implements ElectricHeatService {

    @Resource
    private DataService dataService;

    @Resource
    private ProcessMapper processMapper;

    @Resource
    private CarbonStatisticsService carbonStatisticsService;

    @Override
    public ResponseResult pageList(QueryElectricHeatForm form) {
        Page<ElectricHeat> page = new Page<>(form.getPageNum(), form.getPageSize());
        QueryWrapper<ElectricHeat> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(Objects.nonNull(form.getId()), "material_id", form.getId());
        queryWrapper.eq(Objects.nonNull(form.getYear()), "year", form.getYear());
        queryWrapper.eq(Objects.nonNull(form.getMonth()), "month", form.getMonth());

        String tenantId = HttpContextUtils.getRequest().getHeader("tenant-id");
        queryWrapper.eq("tenant_id", Long.valueOf(tenantId));

        List<Map<String, String>> sortArr = form.getSortArr();
        if (sortArr.size() > 0) {
            for (Map<String, String> map : sortArr) {
                String order = map.get("order");
                String prop = map.get("prop");
                prop = UnderUtil.camel2under(prop);
                if ("ascending".equals(order)) {
                    queryWrapper.orderByAsc(prop);
                } else if ("descending".equals(order)) {
                    queryWrapper.orderByDesc(prop);
                }
            }
        }

        page(page, queryWrapper);

        List<ElectricHeat> electricHeatList = page.getRecords();
        List<QueryElectricHeatDTO> electricHeatDTOList = BeanCopyUtils.copyBeanList(electricHeatList, QueryElectricHeatDTO.class);
        Map<Long, List<EmissionOrigin>> map = dataService.queryTargetStageEmissionOrigin(3).stream().collect(Collectors.groupingBy(EmissionOrigin::getId));
        //封装电力热力名称
        electricHeatDTOList = electricHeatDTOList.stream()
                .peek(dto -> {
                    Process process = processMapper.selectById(dto.getProcessId());
                    if (process != null) {
                        dto.setProcessName(process.getName());
                    }
                    String name = map.get(dto.getMaterialId()).get(0).getName();
                    dto.setName(name);
                }).collect(Collectors.toList());
        PageVo pageVo = new PageVo(page.getTotal(), electricHeatDTOList);
        return ResponseResult.okResult(pageVo);
    }

    @Transactional
    @Override
    public ResponseResult deleteOneOrBatch(List<Integer> ids) {
        if (ids.size() == 1) {
            removeById(ids.get(0));
        } else {
            removeBatchByIds(ids);
        }
        carbonStatisticsService.updateCarbonStatistics(0.0, 0.0);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult getAllYears() {
        List<Integer> years = baseMapper.selectAllYears();
        return ResponseResult.okResult(years);
    }

    @Override
    public ResponseResult modifyElectricHeatInfo(ModifyElectricHeatInfoDto modifyElectricHeatInfoDto) {
        ElectricHeat electricHeat = BeanCopyUtils.copyBean(modifyElectricHeatInfoDto, ElectricHeat.class);
        electricHeat.setCarbonEmission(
                BigDecimal.valueOf(electricHeat.getQuantityBuy())
                        .multiply(BigDecimal.valueOf(electricHeat.getEmissionFactor()))
                        .setScale(2, RoundingMode.UP).doubleValue()
        );
        updateById(electricHeat);
        carbonStatisticsService.updateCarbonStatistics(0.0, 0.0);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult calcYearMonthElectricHeat(CalcElectricHeatCarbonVo vo) {
        //获取指定年指定月指定购入产品的记录
        List<ElectricHeat> electricHeatList = queryTargetYearMonthElectricHeat(vo.getYear(), vo.getMonth(), vo.getMaterialId());
        for (ElectricHeat electricHeat : electricHeatList) {
            BigDecimal emissionFactor = BigDecimal.valueOf(electricHeat.getEmissionFactor());
            BigDecimal quantityBuy = BigDecimal.valueOf(electricHeat.getQuantityBuy());
            double carbonEmission = emissionFactor.multiply(quantityBuy)
                    .setScale(2, RoundingMode.HALF_UP)
                    .doubleValue();
            electricHeat.setCarbonEmission(carbonEmission);

            updateById(electricHeat);
        }
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult addElectricHeatBuyInfo(ElectricHeatBuyInfoVo vo) {
        ElectricHeat electricHeat = BeanCopyUtils.copyBean(vo, ElectricHeat.class);
        BigDecimal emissionFactor = BigDecimal.valueOf(electricHeat.getEmissionFactor());
        BigDecimal quantityBuy = BigDecimal.valueOf(electricHeat.getQuantityBuy());
        double carbonEmission = emissionFactor.multiply(quantityBuy).setScale(2, RoundingMode.UP).doubleValue();
        electricHeat.setCarbonEmission(carbonEmission);

        Long materialId = vo.getMaterialId();
        electricHeat.setType(getElectricHeatTypeByMaterialId(materialId));

        save(electricHeat);
        carbonStatisticsService.updateCarbonStatistics(0.0, 0.0);
        return ResponseResult.okResult();
    }

    private Integer getElectricHeatTypeByMaterialId(Long materialId) {
        List<EmissionOrigin> emissionOriginList = dataService.queryTargetStageEmissionOrigin(3);
        for (EmissionOrigin emissionOrigin : emissionOriginList) {
            if (emissionOrigin.getId().equals(materialId)) {
                if ("电力".equals(emissionOrigin.getName())) {
                    return 1;
                } else if ("热力".equals(emissionOrigin.getName())) {
                    return 2;
                }
            }
        }
        throw new SystemException(AppHttpCodeEnum.DATA_NOT_EXIST);
    }

    private List<ElectricHeat> queryTargetYearMonthElectricHeat(Integer year, Integer month, Integer materialId) {
        LambdaQueryWrapper<ElectricHeat> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ElectricHeat::getMaterialId, materialId);
        queryWrapper.eq(ElectricHeat::getYear, year);
        queryWrapper.eq(ElectricHeat::getMonth, month);
        return list(queryWrapper);
    }
}